package com.wang.tool.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.wang.tool.monitor.InvokeTemplate;
import com.wang.tool.monitor.template.AbsMonitorInvoker;
import com.wang.tool.okhttp.HttpHandler;
import com.wang.tool.okhttp.HttpTemplate;
import okhttp3.Request;
import okhttp3.Response;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @Description excel读取工具
 * @Author shaopeng
 * @Date 2023/7/28
 * @Version 1.0
 */
public class ExcelUtil {

    /**
     * 读取首个excel成json
     *
     * @param url     excel链接 非空
     * @param timeout 读取超时时间
     * @param type    目标类 非空
     * @return
     */
    public static <T> CompletableFuture<List<T>> read2Model(String url, int timeout, Class<T> type) {
        if (CommonUtil.isBlank(url)) {
            throw new IllegalArgumentException("url can not be null");
        }
        if (type == null) {
            throw new IllegalArgumentException("type can not be null");
        }

        return HttpTemplate.async(url, timeout, new HttpHandler<List<T>>() {
            @Override
            public void fillRequest(Request.Builder builder) {
            }

            @Override
            public List<T> read(Response response) throws IOException {
                ArrayList<T> ret = new ArrayList<>();
                try (InputStream input = response.body().byteStream()) {
                    EasyExcel.read(input, type, new ReadListener<T>() {
                                @Override
                                public void invoke(T data, AnalysisContext context) {
                                    ret.add(data);
                                }

                                @Override
                                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                                }
                            })
                            .sheet(0)
                            .doRead();
                }
                return ret;
            }

            @Override
            public List<T> onError(Throwable error) throws Throwable {
                throw error;
            }
        });
    }

    /**
     * 读取首个excel成json
     * 第一行也会读取，最简易的方式
     * key 是列的下标
     *
     * @param url excel链接 非空
     * @param timeout 读取超时时间
     * @return
     */
    public static CompletableFuture<List<Map<Integer, String>>> read2Json(String url, int timeout) {
        if (CommonUtil.isBlank(url)) {
            throw new IllegalArgumentException("url can not be null");
        }

        return HttpTemplate.async(url, timeout, new HttpHandler<List<Map<Integer, String>>>() {
            @Override
            public void fillRequest(Request.Builder builder) {
            }

            @Override
            public List<Map<Integer, String>> read(Response response) throws IOException {

                ArrayList<Map<Integer, String>> ret = new ArrayList<>();
                try (InputStream input = response.body().byteStream()) {
                    EasyExcel.read(input, new AnalysisEventListener<Map<Integer, String>>() {
                                @Override
                                public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                                    ret.add(headMap);
                                }

                                @Override
                                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                                    ret.add(data);
                                }

                                @Override
                                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                                }
                            })
                            .sheet(0)
                            .doRead();
                }
                return ret;
            }

            @Override
            public List<Map<Integer, String>> onError(Throwable error) throws Throwable {
                throw error;
            }
        });
    }


    /**
     * 读取首个excel
     * 边读边处理
     *
     * @param url excel链接 非空
     * @param timeout 读取超时时间 非空
     * @param listener 监听器 非空
     * @param type  目标类 非空
     * @return
     */
    public static <T> CompletableFuture<Void> readingProcess(String url, int timeout, Class<T> type, ReadListener<T> listener) {
        if (CommonUtil.isBlank(url)) {
            throw new IllegalArgumentException("url can not be null");
        }
        if (type == null || listener == null) {
            throw new IllegalArgumentException("type/listener can not be null");
        }

        return HttpTemplate.async(url, timeout, new HttpHandler<Void>() {
            @Override
            public void fillRequest(Request.Builder builder) {

            }

            @Override
            public Void read(Response response) throws IOException {

                try (InputStream input = response.body().byteStream()) {
                    EasyExcel.read(input, type, listener)
                            .sheet(0)
                            .doRead();
                }
                return null;
            }

            @Override
            public Void onError(Throwable error) throws Throwable {
                throw error;
            }
        });
    }


    /**
     * 读取首个excel成json
     *
     * @param file excel链接 非空
     * @param type 目标类 非空
     * @return
     */
    public static <T> List<T> read2Model(File file, Class<T> type) {
        return InvokeTemplate.monitor(ExcelUtil.class, "read2Model", new AbsMonitorInvoker<List<T>>() {
            @Override
            public List<T> internalCall() throws Throwable {
                if (file == null || !file.exists() || !file.isFile()) {
                    throw new IllegalArgumentException("file must be exists file");
                }
                if (type == null) {
                    throw new IllegalArgumentException("type can not be null");
                }
                ArrayList<T> ret = new ArrayList<>();
                EasyExcel.read(file, type, new ReadListener<T>() {
                            @Override
                            public void invoke(T data, AnalysisContext context) {
                                ret.add(data);
                            }

                            @Override
                            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            }
                        })
                        .sheet(0)
                        .doRead();
                return ret;
            }
        });
    }

    /**
     * 读取首个excel成json
     * 第一行也会读取，最简易的方式
     * key 是列的下标
     *
     * @param file 文件 非空&存在
     * @return
     */
    public static List<Map<Integer, String>> read2Json(File file) {
        return InvokeTemplate.monitor(ExcelUtil.class, "read2Json", new AbsMonitorInvoker<List<Map<Integer, String>>>() {
            @Override
            public List<Map<Integer, String>> internalCall() throws Throwable {
                if (file == null || !file.exists() || !file.isFile()) {
                    throw new IllegalArgumentException("file must be exists file");
                }
                ArrayList<Map<Integer, String>> ret = new ArrayList<>();
                EasyExcel.read(file, new AnalysisEventListener<Map<Integer, String>>() {
                            @Override
                            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                                ret.add(headMap);
                            }

                            @Override
                            public void invoke(Map<Integer, String> data, AnalysisContext context) {
                                ret.add(data);
                            }

                            @Override
                            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            }
                        })
                        .sheet(0)
                        .doRead();
                return ret;
            }
        });
    }


    /**
     * 读取首个excel
     * 边读边处理
     *
     * @param file 文件 非空&存在
     * @param type 目标类 非空
     * @param listener 监听器 非空
     * @return
     */
    public static <T> void readingProcess(File file, Class<T> type, ReadListener<T> listener) {
        InvokeTemplate.monitor(ExcelUtil.class, "readingProcess", new AbsMonitorInvoker<Void>() {
            @Override
            public Void internalCall() throws Throwable {
                if (file == null || !file.exists() || !file.isFile()) {
                    throw new IllegalArgumentException("file must be exists file");
                }
                if (type == null || listener == null) {
                    throw new IllegalArgumentException("type/listener can not be null");
                }

                EasyExcel.read(file, type, listener)
                        .sheet(0)
                        .doRead();
                return null;
            }
        });
    }


}
